home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 1 / Mac Magazin and MacEasy Magazine CD - Issue 01.iso / Sharewarebibliothek / Powermac / C64 / SOURCE / Processor.c < prev    next >
Text File  |  1994-06-06  |  8KB  |  378 lines

  1. /*
  2.     Commodore 64 Emulator v0.4      Earle F. Philhower III 
  3.     Copyright (C) 1993-4            (st916w9r@dunx1.ocs.drexel.edu)
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include <AppleEvents.h>
  21. #include "Processor.h"
  22. #include "Modes.h"
  23. #include "Stack.h"
  24. #include "Keyboard.h"
  25. #include "Resources.h"
  26. #include "Preferences.h"
  27.  
  28. extern Cursor commieCursor;
  29. extern void (* instruct[256]) ();
  30. extern byte cycletime[256];
  31. extern int programMode;
  32.  
  33. byte interruptProcessor;
  34. static byte numLeftSameChar;
  35. static void ProcessPerLine(void);
  36. extern void ProcessorLoop(void);
  37.  
  38. void CProcessorLoop(), M68kProcessorLoop(), IntProcessorLoop();
  39.  
  40. void ProcessorLoop()
  41. {
  42.     switch (globalPref.useProcessor)
  43.     {
  44.         case asmProcessor:
  45. #ifndef __MWERKS__
  46.             M68kProcessorLoop();
  47. #else
  48.             IntProcessorLoop();
  49. #endif
  50.             break;
  51.         case cProcessor:
  52.             CProcessorLoop();
  53.             break;
  54.         case intCProcessor:
  55.             IntProcessorLoop();
  56.             break;
  57.     }
  58. }
  59.  
  60. void CProcessorLoop()
  61. {
  62.     int scanLines, vicCalls;
  63.     byte instructCode, oldMemoryMap, processorCycles, col;
  64.     Str255 str;
  65.     
  66.     programMode=kRunning;
  67.     
  68.     ShowVICWindow();
  69.     
  70.     /* Set up window, cursor for running state */
  71.     GetIndString(str, kWindowStrings, kRunningWindow);
  72.     SetVICTitle(str);
  73.     SetCursor(&commieCursor);
  74.     ObscureCursor();
  75.     
  76.     /* Set up the memory dereferences, and store current map */
  77.     oldMemoryMap=*RAMp1;
  78.     SetUpMemoryMap();
  79.     
  80.     /* Some flags and counters necessray to be initialized */
  81.     interruptProcessor=0;
  82.     numLeftSameChar=0;
  83.     processorCycles=0;
  84.     scanLines=0;
  85.     vicCalls=0;
  86.     
  87.     while (interruptProcessor==0)
  88.     {
  89.         instructCode = ImmediateByte(); pc++;
  90.         processorCycles += cycletime[instructCode];
  91.         (*instruct[instructCode])();
  92.  
  93.         /* Set up the memory map if it has changed */
  94.         if (*RAMp1!=oldMemoryMap)
  95.         {
  96.             SetUpMemoryMap();
  97.             oldMemoryMap=*RAMp1;
  98.         }
  99.  
  100.         /* If we've done 35 cycles, we've gone through 1 scanline */
  101.         if (processorCycles>35)
  102.         {
  103.             processorCycles=0;
  104.  
  105.             /* Update the current VIC scan register */
  106.             if (++RAM[0xd012]==0) RAM[0xd011] ^= 128;
  107.             RAM[0xd018] |=1;
  108.  
  109.             /* If we've gone through 350 lines, we've due for an interrupt */
  110.             if (++scanLines>350)
  111.             {
  112.                 scanLines=0;
  113.             
  114.                 /* Set raster to 0 line */
  115.                 RAM[0xd012]=0;
  116.                 RAM[0xd011]&=127;
  117.             
  118.                 /* Currently we just update the keyboard registers */
  119.                 ProcessPerLine();
  120.                 if (++vicCalls==2)
  121.                 {
  122.                     RedrawVIC();
  123.                     vicCalls=0;
  124.                 }
  125.                 
  126.                 /* Call interrupt routine if interrupts enabled */
  127.                 if ((flags&INT)==0)
  128.                 {
  129.                     PushWord(pc);
  130.                     Push(flags);
  131.                     pc=WordAt(IrqTo);
  132.                 }
  133.             }
  134.         }
  135.         
  136.         /* Set up the keyboard register according to precomputed values */
  137.         RAM[0xdc01]=scanCode[RAM[0xdc00]];
  138.     }
  139.     
  140.     /* Done processing, reset window, cursor */
  141.     RedrawVIC();
  142.     SetCursor(&qd.arrow);
  143.     GetIndString(str, kWindowStrings, kSuspendedWindow);
  144.     SetVICTitle(str);
  145.     
  146.     programMode=kSleeping;
  147. }
  148.  
  149. extern void    CPU(void);
  150.  
  151. void M68kProcessorLoop()
  152. {
  153. #ifndef __MWERKS__
  154.     int                    vicCalls;
  155.     byte                *d012, *d011, *d018;
  156.     Str255                str;
  157.     
  158.     ShowVICWindow();
  159.  
  160.     /* Set up window, cursor for running state */
  161.     GetIndString(str, kWindowStrings, kRunningWindow);
  162.     SetVICTitle(str);
  163.     SetCursor(&commieCursor);
  164.     ObscureCursor();
  165.     
  166.     /* Initialize precomputed addresses (minimal speed gain) */
  167.     d012=&RAM[0xd012];
  168.     d011=&RAM[0xd011];
  169.     d018=&RAM[0xd018];
  170.  
  171.     /* Store current map */
  172.     SetUpMemoryMap();
  173.     
  174.     /* Some flags and counters necessary to be initialized */
  175.     interruptProcessor=0;
  176.     numLeftSameChar=0;
  177.     vicCalls=0;
  178.  
  179.     while (interruptProcessor==0) {
  180.         /*    Most of the functionality of the CPU has been moved to this function.
  181.          *    This function will execute for 350 screen lines.
  182.          */
  183.         CPU();
  184.  
  185.         /* If we've gone through 350 lines, we've due for an interrupt */
  186.         /* Set raster to 0 line */
  187.         *d012=0;
  188.         *d011&=127;
  189.     
  190.         /* Currently we just update the keyboard registers */
  191.         ProcessPerLine();
  192.  
  193.         if (++vicCalls==2)
  194.             {
  195.             RedrawVIC();
  196.             vicCalls=0;
  197.             }
  198.         
  199.         /* Call interrupt routine if interrupts enabled */
  200.         if ((flags&INT)==0)
  201.             {
  202.             PushWord(pc);
  203.             Push(flags);
  204.             pc=WordAt(IrqTo);
  205.             }
  206.         }
  207.  
  208.     /* Done processing, reset window, cursor */
  209.     RedrawVIC();
  210.     SetCursor(&qd.arrow);
  211.     GetIndString(str, kWindowStrings, kSuspendedWindow);
  212.     SetVICTitle(str);
  213. #endif
  214. }
  215.  
  216.  
  217. /* Called once per scanline, currently check for keypress or mouse button */ 
  218. static void ProcessPerLine()
  219. {
  220.     EventRecord evt;
  221.     WindowPtr theWind;
  222.     int x;
  223.     char theChar;
  224.     
  225.     /* We keep the same keyboard map for 1/30th of a second */
  226.     if (numLeftSameChar==0)
  227.     {
  228.         numLeftSameChar=2;
  229.         
  230.         /* Check for any key or mouse press */
  231.         if (GetNextEvent(-1, &evt)!=false)
  232.             switch(evt.what)
  233.             {
  234.             case mouseDown:
  235.                 /* A mouseclick stops our simulation */
  236.                 MiniHandleMouseDown(evt);
  237.                 break;
  238.                 
  239.             case updateEvt:
  240.                 theWind=(WindowPtr)evt.message;
  241.                 BeginUpdate(theWind);
  242.                 switch (GetWRefCon(theWind))
  243.                 {
  244.                     case kVICWindow:
  245.                         break;
  246.                     case kDirWindow:
  247.                         RedrawDir();
  248.                         break;
  249.                     case kAboutWindow:
  250.                         break;
  251.                 }
  252.                 EndUpdate(theWind);
  253.                 break;
  254.                 
  255.             case app4Evt:
  256.                 if ((evt.message&1)==0) interruptProcessor=1;
  257.                 break;
  258.                 
  259.             case kHighLevelEvent:
  260.                 AEProcessAppleEvent(&evt);
  261.                 break;
  262.                 
  263.             case keyDown:
  264.             case autoKey:
  265.                 /* A keypress is simulated by fudging the CIA registers */
  266.                 theChar = evt.message&charCodeMask;
  267.                 if ((evt.modifiers&cmdKey)!=0) DoMenuChoice(MenuKey(theChar));
  268.                 else AppleScanKeyboard(evt.message&charCodeMask, evt.modifiers);
  269.             }
  270.         
  271.         /* No keypress, so clear out keyboard register fudge */
  272.         else
  273.         {
  274.             for (x=0; x<256; x++) scanCode[x]=0xff;
  275.             SystemTask();
  276.         }
  277.     }
  278.     else numLeftSameChar--;
  279. }
  280.  
  281.  
  282. MiniHandleMouseDown(event)
  283. EventRecord event;
  284. {
  285.     WindowPtr theWind;
  286.     GrafPtr gp;
  287.     Point x;
  288.     short thePart;
  289.     extern Rect dragRect;
  290.     
  291.     thePart=FindWindow(event.where, &theWind);
  292.     switch(thePart)
  293.     {
  294.     case inSysWindow:
  295.         SystemClick(&event, theWind);
  296.         interruptProcessor=1;
  297.         break;
  298.         
  299.     case inDrag:
  300.         if (GetWRefCon(theWind)==kVICWindow) DragVICWindow(&event);
  301.         else DragWindow(theWind, event.where, &dragRect);
  302.         break;
  303.         
  304.     case inMenuBar:
  305.         DoMenuChoice(MenuSelect(event.where));
  306.         break;
  307.     
  308.     case inContent:
  309.         SelectWindow(theWind);
  310.         interruptProcessor=1;
  311.         break;
  312.     }
  313. }
  314.  
  315.  
  316. void IntProcessorLoop()
  317. {
  318.     int                    vicCalls;
  319.     byte                *d012, *d011, *d018;
  320.     Str255                str;
  321.     
  322.     ShowVICWindow();
  323.  
  324.     /* Set up window, cursor for running state */
  325.     GetIndString(str, kWindowStrings, kRunningWindow);
  326.     SetVICTitle(str);
  327.     SetCursor(&commieCursor);
  328.     ObscureCursor();
  329.     
  330.     /* Initialize precomputed addresses (minimal speed gain) */
  331.     d012=&RAM[0xd012];
  332.     d011=&RAM[0xd011];
  333.     d018=&RAM[0xd018];
  334.  
  335.     /* Store current map */
  336.     SetUpMemoryMap();
  337.     
  338.     /* Some flags and counters necessary to be initialized */
  339.     interruptProcessor=0;
  340.     numLeftSameChar=0;
  341.     vicCalls=0;
  342.  
  343.     while (interruptProcessor==0) {
  344.         /*    Most of the functionality of the CPU has been moved to this function.
  345.          *    This function will execute for 350 screen lines.
  346.          */
  347.         IntegratedProcessor(&a, &x, &y, &flags, &sp, &pc, memory, RAM);
  348.  
  349.         /* If we've gone through 350 lines, we've due for an interrupt */
  350.         /* Set raster to 0 line */
  351.         *d012=0;
  352.         *d011&=127;
  353.     
  354.         /* Currently we just update the keyboard registers */
  355.         ProcessPerLine();
  356.  
  357.         if (++vicCalls==2)
  358.             {
  359.             RedrawVIC();
  360.             vicCalls=0;
  361.             }
  362.         
  363.         /* Call interrupt routine if interrupts enabled */
  364.         if ((flags&INT)==0)
  365.             {
  366.             PushWord(pc);
  367.             Push(flags);
  368.             pc=WordAt(IrqTo);
  369.             }
  370.         }
  371.  
  372.     /* Done processing, reset window, cursor */
  373.     RedrawVIC();
  374.     SetCursor(&qd.arrow);
  375.     GetIndString(str, kWindowStrings, kSuspendedWindow);
  376.     SetVICTitle(str);
  377. }
  378.